﻿namespace EFS.RC.CC.Trackers.OfficeService.Remote
{
	/// <summary>
	/// Agents tackers
	/// </summary>
	internal class Applications : EFS.Common.Async.RepeaterSlot
	{
		#region Composition

		// sync access
		private System.Object syncAccess = new System.Object();

		// Team to track
		private EFS.RC.CC.Presences.Operators.OfficeService.Team operatorsTeam = null;

		// Agents status message
		private EFS.RC.CC.Messages.Agents.StatusList agentsStatusMessage = null;

		// Quoue status message
		private EFS.RC.CC.Messages.HuntQueue.StatusList agentsHuntQueueStausListMessage = null;

		// wallboards
		System.Collections.Generic.List<EFS.RC.CC.Applications.Remote.WallBoard.Monitor> wallBoardApplicationList =
			new System.Collections.Generic.List<EFS.RC.CC.Applications.Remote.WallBoard.Monitor>();

		#endregion

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="supervisorOperator"></param>
		public Applications(EFS.RC.CC.Presences.Operators.OfficeService.Team operatorsTeam) : base(3)
		{
			// check
			EFS.Common.Verify.Reference(operatorsTeam, "operatorsTeam");

			// set internals
			this.operatorsTeam = operatorsTeam;
		}

		#endregion

		#region Usage

		/// <summary>
		/// Describe this object into a nice formated string
		/// </summary>
		/// <returns></returns>
		public override System.String Describe()
		{
			return System.String.Format("EFS.RC.CC.Trackers.OfficeService.Remote.Applications [{0}]", operatorsTeam.Describe());
		}

		/// <summary>
		/// Register vallboard
		/// </summary>
		/// <param name="wallBoard"></param>
		public void RegisterWallBoardApplication(EFS.RC.CC.Applications.Remote.WallBoard.Monitor wallBoardApplication)
		{
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// check
				if (wallBoardApplicationList.Contains(wallBoardApplication))
				{
					throw new System.InvalidOperationException("WallBoard already registered");
				}

				try
				{
					// register for delegate
					wallBoardApplication.AsinkTerminatedDelegate.Register(WallBoardApplicationTerminated);

					// add local
					wallBoardApplicationList.Add(wallBoardApplication);
				}
				catch (System.Exception ex)
				{
					// log
					EFS.EventLog.Log.LogException(ex, this);
				}
			}
		}

		#endregion

		#region Runtime

		/// <summary>
		/// Unhandled exception
		/// </summary>
		/// <param name="ex"></param>
		protected override void OnException(System.Exception ex)
		{
			// check
			EFS.Common.Verify.Reference(ex, "ex");

			// log
			EFS.EventLog.Log.LogException(ex, this);

			// SAL
			EFS.RC.CC.Tools.Loggers.SAL.Add(null, "OnException", ex, this); 

			// shut down
			BeginShutdown();
		}

		/// <summary>
		/// Send agents activity status
		/// </summary>
		protected override void RepeateAction()
		{
			// log
			// ~ commented for performance ~ EFS.EventLog.Log.LogInfo("SendActivityStatus", this);

			// update activity
			agentsHuntQueueStausListMessage = operatorsTeam.AgentsHunterQueue.GetHuntQueueStatusMessage();
			agentsStatusMessage = operatorsTeam.GetAgentsStatusMessage();

			// send activity
			SendActivityStatusToSupervisors();
			SendActivityStatusToWallBoards();

			// let GC get this
			agentsHuntQueueStausListMessage = null;
			agentsStatusMessage = null;
		}

		/// <summary>
		/// Send activity status to supervisors
		/// </summary>
		private void SendActivityStatusToSupervisors()
		{
			// log
			//EFS.EventLog.Log.LogInfo("SendActivityStatusToSupervisors", this);

			//send message
			operatorsTeam.ForEachSupervisor(SendActivityStatusToSupervisor);
		}

		/// <summary>
		/// Send activity status to wallboards
		/// </summary>
		private void SendActivityStatusToWallBoards()
		{
			// log
			//EFS.EventLog.Log.LogInfo("SendActivityStatusToWallBoards", this);

			// wallboards
			System.Collections.Generic.List<EFS.RC.CC.Applications.Remote.WallBoard.Monitor> wallBoardApplicationList = null;

			// get actual list
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// copy locally
				wallBoardApplicationList = new System.Collections.Generic.List<EFS.RC.CC.Applications.Remote.WallBoard.Monitor>(this.wallBoardApplicationList);
			}

			// send
			foreach (EFS.RC.CC.Applications.Remote.WallBoard.Monitor wallBoardApplication in wallBoardApplicationList)
			{
				try
				{
					// send messages
					wallBoardApplication.BeginDataSend(agentsStatusMessage);
					wallBoardApplication.BeginDataSend(agentsHuntQueueStausListMessage);
				}
				catch (System.Exception ex)
				{
					EFS.EventLog.Log.LogException(ex, this);
				}
			}
		}

		/// <summary>
		/// Send agents activity status
		/// </summary>
		private void SendActivityStatusToSupervisor(EFS.RC.CC.Presences.Operators.OfficeService.Supervisors.Supervisor supervisorPresence)
		{
			// log
			//EFS.EventLog.Log.LogInfo("SendActivityStatusToSupervisor", this);

			// check
			EFS.Common.Verify.Reference(supervisorPresence, "supervisorPresence");

			// get application
			EFS.RC.CC.Applications.Remote.Operators.SupervisorCentral supervisorCentralApplication = supervisorPresence.SupervisorCentralApplication;

			// check
			if (null != supervisorCentralApplication)
			{
				try
				{
					// send messages
					supervisorCentralApplication.BeginDataSend(agentsStatusMessage);
					supervisorCentralApplication.BeginDataSend(agentsHuntQueueStausListMessage);
				}
				catch (System.Exception ex)
				{
					EFS.EventLog.Log.LogException(ex, this);
				}
			}
		}

		/// <summary>
		/// Send agents activity status
		/// </summary>
		private void SendQueueStatusToSupervisor(EFS.RC.CC.Presences.Operators.OfficeService.Supervisors.Supervisor supervisorPresence)
		{
			// log
			//EFS.EventLog.Log.LogInfo("SendQueueStatusToSupervisor", this);

			// check
			EFS.Common.Verify.Reference(supervisorPresence, "supervisorPresence");

			// get application
			EFS.RC.CC.Applications.Remote.Operators.SupervisorCentral supervisorCentralApplication = supervisorPresence.SupervisorCentralApplication;

			// check
			if (null != supervisorCentralApplication)
			{
				// try send message
				supervisorCentralApplication.BeginDataSend(agentsHuntQueueStausListMessage);
			}
		}

		/// <summary>
		/// Application
		/// </summary>
		private void WallBoardApplicationTerminated(EFS.RC.CC.Applications.Remote.Messaging remoteMessagingApplication)
		{
			// sync access
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// app is wallboard
				EFS.RC.CC.Applications.Remote.WallBoard.Monitor wallBoardApplication = remoteMessagingApplication as EFS.RC.CC.Applications.Remote.WallBoard.Monitor;

				// check if we have any
				if (!wallBoardApplicationList.Contains(wallBoardApplication))
				{
					// different
					throw new System.InvalidOperationException("Terminated WallBoard Application is not registered");
				}

				// remove
				wallBoardApplicationList.Remove(wallBoardApplication);
			}
		}

		#endregion // Runtime
	}
}

